Skip to content

Restore pluggable email backend for task failure/retry alerts#69877

Merged
potiuk merged 1 commit into
apache:mainfrom
potiuk:restore-pluggable-email-backend
Jul 20, 2026
Merged

Restore pluggable email backend for task failure/retry alerts#69877
potiuk merged 1 commit into
apache:mainfrom
potiuk:restore-pluggable-email-backend

Conversation

@potiuk

@potiuk potiuk commented Jul 14, 2026

Copy link
Copy Markdown
Member

What

Restore the ability to deliver email_on_failure / email_on_retry task alerts through the
configured [email] email_backend (SES, SendGrid, or any custom callable), which regressed
in #57354.

Why

email_on_failure / email_on_retry are deprecated (slated for Airflow 4, migrate to
SmtpNotifier) but still functional. Since #57354, task failure/retry emails are routed
unconditionally through SmtpNotifier, silently ignoring the [email] email_backend
configuration. Deployments using a custom email_backend (Amazon SES, SendGrid,
org-internal) stopped receiving failure/retry alerts even though the config option still
exists and the deprecated params still work. This restores that behaviour while keeping the
single-notifier design #57354 introduced.

How

_send_error_email_notification (shared by both the worker task-runner path and the
DAG-processor callback path) resolves the delivery mechanism from the existing
[email] email_backend option — no new configuration is added:

  1. A non-default [email] email_backend is transparently wrapped in a new
    LegacyEmailBackendNotifier (airflow.sdk.execution_time.email_backend), so existing
    SES/SendGrid setups keep working unchanged. The backend is resolved from config at notify
    time, so the Task SDK keeps no static dependency on airflow.utils.email.
  2. Otherwise the default SmtpNotifier is used, exactly as today.

The notifier lives in the Task SDK next to its only caller, so no additional provider needs
to be installed for a custom email backend to keep working.

Because both failure-email entry points funnel through the same function, the selected
backend is used consistently regardless of how the task failed (normal failure vs.
zombie/killed).

Changes after review

An earlier revision of this PR added a new [email] email_notifier config option. Per
eladkal's review comment,
that option has been dropped — the goal is to complete the Core→SMTP migration and
deprecate email settings in core, not add new ones. The fix now rides entirely on the
email_backend option that already exists, and config.yml is untouched by this PR.

Tests

  • TestEmailNotifications (task-sdk): default still uses SmtpNotifier (unchanged
    regression tests), custom email_backend wrapped and invoked with the rendered fields,
    unresolvable email_backend logged (no raise).
  • TestExecuteEmailCallbacks (DAG-processor path): unchanged and green — confirms both
    entry points stay consistent.
  • test_email_backend.py (task-sdk): unit tests for LegacyEmailBackendNotifier dispatch.

Notes

  • The deprecated email_on_* params are not un-deprecated; this only keeps their
    existing behaviour pluggable until removal in Airflow 4.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.8)

Generated-by: Claude Code (Opus 4.8) following the guidelines

Comment thread airflow-core/src/airflow/config_templates/config.yml Outdated
@potiuk
potiuk force-pushed the restore-pluggable-email-backend branch 2 times, most recently from 2f222f9 to 2e92be7 Compare July 20, 2026 10:24
@potiuk
potiuk marked this pull request as ready for review July 20, 2026 10:31
@potiuk
potiuk force-pushed the restore-pluggable-email-backend branch 2 times, most recently from d3c1bcc to fd671dc Compare July 20, 2026 10:49
Comment thread task-sdk/tests/task_sdk/execution_time/test_email_backend.py Outdated
Comment thread task-sdk/tests/task_sdk/execution_time/test_task_runner.py
Comment thread task-sdk/src/airflow/sdk/execution_time/email_backend.py Outdated
@potiuk
potiuk force-pushed the restore-pluggable-email-backend branch from fd671dc to 816add6 Compare July 20, 2026 10:59

@amoghrajesh amoghrajesh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good after the comments are handled.

Comment thread task-sdk/src/airflow/sdk/execution_time/task_runner.py Outdated
Comment thread task-sdk/tests/task_sdk/execution_time/test_task_runner.py Outdated
Comment thread task-sdk/tests/task_sdk/execution_time/test_task_runner.py Outdated
Comment thread task-sdk/src/airflow/sdk/execution_time/task_runner.py
Comment thread task-sdk/src/airflow/sdk/execution_time/email_backend.py Outdated
Comment thread task-sdk/src/airflow/sdk/execution_time/task_runner.py Outdated
@potiuk potiuk added this to the Airflow 3.3.1 milestone Jul 20, 2026
@potiuk potiuk added the backport-to-v3-3-test Backport to v3-3-test label Jul 20, 2026
Comment thread task-sdk/src/airflow/sdk/execution_time/email_backend.py Outdated
@potiuk
potiuk force-pushed the restore-pluggable-email-backend branch from 816add6 to 0ff8364 Compare July 20, 2026 11:35
Since apache#57354, task email_on_failure / email_on_retry alerts were routed
unconditionally through SmtpNotifier, silently ignoring the
[email] email_backend configuration. Custom backends (SES, SendGrid,
org-internal) stopped delivering failure/retry emails even though the
deprecated email_on_* parameters still worked.

This restores the old behaviour using the existing [email] email_backend
option -- no new configuration is introduced:

- A non-default [email] email_backend is transparently wrapped in a new
  LegacyEmailBackendNotifier, so existing SES / SendGrid / custom backends
  keep delivering alerts unchanged. The backend is resolved from config at
  notify time, so the Task SDK keeps no static dependency on
  airflow.utils.email.
- Otherwise the default SmtpNotifier is used, exactly as before.

The notifier lives in the Task SDK (airflow.sdk.execution_time.email_backend)
next to its only caller, so no extra provider needs to be installed for a
custom email backend to keep working.

Both failure-email entry points (the worker task-runner path and the
DAG-processor callback path) funnel through the same function, so the
selected backend is used consistently regardless of how the task failed.

The deprecated email_on_* parameters are not un-deprecated; this only keeps
their existing behaviour pluggable until removal in Airflow 4.
@potiuk
potiuk force-pushed the restore-pluggable-email-backend branch from 0ff8364 to 4d0e66d Compare July 20, 2026 11:44
@potiuk
potiuk merged commit f7dec02 into apache:main Jul 20, 2026
107 checks passed
@potiuk
potiuk deleted the restore-pluggable-email-backend branch July 20, 2026 13:14
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-3-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

Status Branch Result
v3-3-test PR Link

github-actions Bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jul 20, 2026
…y alerts (apache#69877)

Since apache#57354, task email_on_failure / email_on_retry alerts were routed
unconditionally through SmtpNotifier, silently ignoring the
[email] email_backend configuration. Custom backends (SES, SendGrid,
org-internal) stopped delivering failure/retry emails even though the
deprecated email_on_* parameters still worked.

This restores the old behaviour using the existing [email] email_backend
option -- no new configuration is introduced:

- A non-default [email] email_backend is transparently wrapped in a new
  LegacyEmailBackendNotifier, so existing SES / SendGrid / custom backends
  keep delivering alerts unchanged. The backend is resolved from config at
  notify time, so the Task SDK keeps no static dependency on
  airflow.utils.email.
- Otherwise the default SmtpNotifier is used, exactly as before.

The notifier lives in the Task SDK (airflow.sdk.execution_time.email_backend)
next to its only caller, so no extra provider needs to be installed for a
custom email backend to keep working.

Both failure-email entry points (the worker task-runner path and the
DAG-processor callback path) funnel through the same function, so the
selected backend is used consistently regardless of how the task failed.

The deprecated email_on_* parameters are not un-deprecated; this only keeps
their existing behaviour pluggable until removal in Airflow 4.
(cherry picked from commit f7dec02)

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jul 20, 2026
…y alerts (apache#69877)

Since apache#57354, task email_on_failure / email_on_retry alerts were routed
unconditionally through SmtpNotifier, silently ignoring the
[email] email_backend configuration. Custom backends (SES, SendGrid,
org-internal) stopped delivering failure/retry emails even though the
deprecated email_on_* parameters still worked.

This restores the old behaviour using the existing [email] email_backend
option -- no new configuration is introduced:

- A non-default [email] email_backend is transparently wrapped in a new
  LegacyEmailBackendNotifier, so existing SES / SendGrid / custom backends
  keep delivering alerts unchanged. The backend is resolved from config at
  notify time, so the Task SDK keeps no static dependency on
  airflow.utils.email.
- Otherwise the default SmtpNotifier is used, exactly as before.

The notifier lives in the Task SDK (airflow.sdk.execution_time.email_backend)
next to its only caller, so no extra provider needs to be installed for a
custom email backend to keep working.

Both failure-email entry points (the worker task-runner path and the
DAG-processor callback path) funnel through the same function, so the
selected backend is used consistently regardless of how the task failed.

The deprecated email_on_* parameters are not un-deprecated; this only keeps
their existing behaviour pluggable until removal in Airflow 4.
(cherry picked from commit f7dec02)

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
dabla pushed a commit to dabla/airflow that referenced this pull request Jul 21, 2026
…ache#69877)

Since apache#57354, task email_on_failure / email_on_retry alerts were routed
unconditionally through SmtpNotifier, silently ignoring the
[email] email_backend configuration. Custom backends (SES, SendGrid,
org-internal) stopped delivering failure/retry emails even though the
deprecated email_on_* parameters still worked.

This restores the old behaviour using the existing [email] email_backend
option -- no new configuration is introduced:

- A non-default [email] email_backend is transparently wrapped in a new
  LegacyEmailBackendNotifier, so existing SES / SendGrid / custom backends
  keep delivering alerts unchanged. The backend is resolved from config at
  notify time, so the Task SDK keeps no static dependency on
  airflow.utils.email.
- Otherwise the default SmtpNotifier is used, exactly as before.

The notifier lives in the Task SDK (airflow.sdk.execution_time.email_backend)
next to its only caller, so no extra provider needs to be installed for a
custom email backend to keep working.

Both failure-email entry points (the worker task-runner path and the
DAG-processor callback path) funnel through the same function, so the
selected backend is used consistently regardless of how the task failed.

The deprecated email_on_* parameters are not un-deprecated; this only keeps
their existing behaviour pluggable until removal in Airflow 4.
potiuk added a commit that referenced this pull request Jul 21, 2026
…y alerts (#69877) (#70129)

Since #57354, task email_on_failure / email_on_retry alerts were routed
unconditionally through SmtpNotifier, silently ignoring the
[email] email_backend configuration. Custom backends (SES, SendGrid,
org-internal) stopped delivering failure/retry emails even though the
deprecated email_on_* parameters still worked.

This restores the old behaviour using the existing [email] email_backend
option -- no new configuration is introduced:

- A non-default [email] email_backend is transparently wrapped in a new
  LegacyEmailBackendNotifier, so existing SES / SendGrid / custom backends
  keep delivering alerts unchanged. The backend is resolved from config at
  notify time, so the Task SDK keeps no static dependency on
  airflow.utils.email.
- Otherwise the default SmtpNotifier is used, exactly as before.

The notifier lives in the Task SDK (airflow.sdk.execution_time.email_backend)
next to its only caller, so no extra provider needs to be installed for a
custom email backend to keep working.

Both failure-email entry points (the worker task-runner path and the
DAG-processor callback path) funnel through the same function, so the
selected backend is used consistently regardless of how the task failed.

The deprecated email_on_* parameters are not un-deprecated; this only keeps
their existing behaviour pluggable until removal in Airflow 4.
(cherry picked from commit f7dec02)

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants